package com.milling.framework.websocket;

import com.milling.business.service.IWmsNeedleSorttingService;
import com.milling.common.utils.modbus.ModbusServiceFactory;
import com.milling.common.utils.modbus.ModbusTcpService;
import com.milling.system.service.ISysConfigService;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Component
public class AlertConfirmWebSocketHandler extends TextWebSocketHandler {
    private static final Logger logger = LoggerFactory.getLogger(AlertConfirmWebSocketHandler.class);

    private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
    private static final int ALERT_CONFIG_ID = 8;
    private final Lock lock = new ReentrantLock();

    @Autowired
    private ISysConfigService sysConfigService;

    // 从参数中读取IP、端口、slaveId和连接池大小
    @Value("${modbus.sorting.host:192.168.237.178}")
    private String host; // 从配置文件或命令行参数中读取

    @Value("${modbus.sorting.port:502}")
    private int port; // 从配置文件或命令行参数中读取

    @Value("${modbus.sorting.poolSize:5}")
    private int poolSize; // 从配置文件或命令行参数中读取

    @Value("${modbus.sorting.slaveId:1}")
    private int slaveId;

    // 获取Modbus服务实例
    private ModbusTcpService modbusTcpService;

    @Autowired
    private IWmsNeedleSorttingService wmsNeedleSorttingService;

    @PostConstruct
    public void init() {
        // 初始化 Modbus 服务
        modbusTcpService = ModbusServiceFactory.getModbusService(host, port, poolSize);
        logger.info("AlertConfirmWebSocketHandler Modbus服务初始化完成 - {}:{}", host, port);

        // 初始化扫码器连接
//        initConnection();
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.put(session.getId(), session);
        System.out.println("[" + new Date() + "] WebSocket连接建立: " + session.getId());

        try {
            session.sendMessage(new TextMessage(
                    "{\"type\":\"connection\",\"msg\":\"警报监控连接成功\"}"
            ));
        } catch (IOException e) {
            System.err.println("[" + new Date() + "] 欢迎消息发送失败: " + e.getMessage());
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, org.springframework.web.socket.CloseStatus status) throws Exception {
        sessions.remove(session.getId());
        System.out.println("[" + new Date() + "] WebSocket连接关闭: " + session.getId() + ", 原因: " + status.getReason());
    }

    public void sendAlert(String message) {
        if (sessions.isEmpty()) {
            System.out.println("[" + new Date() + "] 警告: 没有活跃的WebSocket连接，无法发送消息");
            return;
        }

        TextMessage textMessage = new TextMessage(message);
        sessions.values().forEach(session -> {
            try {
                if (session.isOpen()) {
                    synchronized (session) {
                        session.sendMessage(textMessage);
                    }
                    System.out.println("[" + new Date() + "] 消息已发送至: " + session.getId());
                }
            } catch (IOException e) {
                System.err.println("[" + new Date() + "] 发送消息失败: " + e.getMessage());
            }
        });
    }

    @Scheduled(fixedRate = 30000)
    public void sendHeartbeat() {
        if (sessions.isEmpty()) return;

        String heartbeatMsg = "{\"type\":\"heartbeat\"}";
        sessions.values().forEach(session -> {
            try {
                if (session.isOpen()) {
                    synchronized (session) {
                        session.sendMessage(new TextMessage(heartbeatMsg));
                    }
                }
            } catch (IOException e) {
                System.err.println("[" + new Date() + "] 心跳发送失败: " + e.getMessage());
            }
        });
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
//        System.out.println("[" + new Date() + "] 收到客户端消息: " + payload + " | 来自: " + session.getId());

        if ("ping".equalsIgnoreCase(payload.trim())) {
//            System.out.println("[" + new Date() + "] 收到心跳ping，回复pong");
            try {
                if (session.isOpen()) {
                    session.sendMessage(new TextMessage("pong"));
                }
            } catch (IOException e) {
                System.err.println("[" + new Date() + "] 回复pong失败: " + e.getMessage());
            }
            return;
        }

        if ("confirm".equals(payload) || "cancel".equals(payload)) {
            if ("confirm".equals(payload)) {
                sysConfigService.updateConfigValue(ALERT_CONFIG_ID, "off");
                System.out.println("[" + new Date() + "] 用户操作完成，已将配置更新为 off");
            }
            try {
                session.sendMessage(new TextMessage(
                        "{\"type\":\"ack\",\"msg\":\"操作已处理\"}"
                ));
            } catch (IOException e) {
                System.err.println("[" + new Date() + "] ACK发送失败: " + e.getMessage());
            }
        } else if ("scannerConfirm".equals(payload)) {
            logger.info("scannerConfirm");
        } else if ("scannerCancel".equals(payload)) {
            logger.info("scannerCancel");
        } else if ("continueSorting".equals(payload)) {
            logger.info("continueSorting, 用户选择继续分拣");
            try {
                modbusTcpService.writeHoldingRegister(slaveId,5030, 2);//继续分拣下一个托盘
                logger.info("继续分拣，给5030地址写2成功");
            } catch (ModbusTransportException ex) {
                ex.printStackTrace();
                logger.error("继续分拣，给5030地址写2失败");
            } catch (Exception ex) {
                ex.printStackTrace();
                logger.error("继续分拣，给5030地址写2失败");
            }
//            GlobalVariable.initSortingParam();
            wmsNeedleSorttingService.initSortingParam();
        } else if ("completeSorting".equals(payload)) {
            logger.info("completeSorting, 用户选择结束分拣");
            try {
                modbusTcpService.writeHoldingRegister(slaveId,5030, 1);//结束分拣
                logger.info("继续分拣，给5030地址写1成功");
            } catch (ModbusTransportException ex) {
                ex.printStackTrace();
                logger.error("继续分拣，给5030地址写1失败");
            } catch (Exception ex) {
                ex.printStackTrace();
                logger.error("继续分拣，给5030地址写1失败");
            }
//            GlobalVariable.initSortingParam();
            wmsNeedleSorttingService.initSortingParam();
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.err.println("[" + new Date() + "] WebSocket传输错误: " + exception.getMessage());
        System.err.println("会话ID: " + session.getId());
        exception.printStackTrace();

        try {
            session.close();
        } catch (IOException e) {
            System.err.println("[" + new Date() + "] 关闭会话失败: " + e.getMessage());
        }
    }

    @Scheduled(fixedRate = 15000)
    public void checkHeartbeat() {
        if (sessions.isEmpty()) {
            return;
        }

        long now = System.currentTimeMillis();
        sessions.values().forEach(session -> {
            if (session.isOpen()) {
                try {
                    String heartbeatMsg = "heartbeat:" + now;
                    synchronized (session) {
                        session.sendMessage(new TextMessage(heartbeatMsg));
                    }
//                    System.out.println("[" + new Date() + "] 发送后端心跳: " + heartbeatMsg);
                } catch (IOException e) {
                    System.err.println("[" + new Date() + "] 后端心跳发送失败: " + e.getMessage());
                }
            }
        });
    }
}
